<template>
  <div class="monitor-box">
    <div class="left-box">
      <div class="control-box">
        <div class="search-box box-shadow">
          <a-form>
            <a-form-item label="标段">
              <a-select
                  v-model:value="cellQueryFormState.sections[0].sectionId">
                <a-select-option
                    v-for="section in sections"
                    :key="section.sectionId" :value="section.sectionId">
                  {{section.sectionName}}
                </a-select-option>
              </a-select>
            </a-form-item>
            <a-form-item label="仅显示当日施工单元">
              <a-switch
                  :defaultChecked="cellQueryFormState.workToday==1"
                  @change="()=>{cellQueryFormState.workToday=cellQueryFormState.workToday==1?undefined:1}"/>
            </a-form-item>
            <a-form-item label="单元状态">
              <a-select
                  v-model:value="cellQueryFormState.status">
                <a-select-option
                    v-for="cellStatus in cellStatusDict.dict2"
                    :key="cellStatus.statusCode" :value="cellStatus.statusCode">
                  {{cellStatus.statusName}}
                </a-select-option>
              </a-select>
            </a-form-item>
            <a-form-item label="单元名称">
              <a-input v-model:value="cellQueryFormState.cellName"></a-input>
            </a-form-item>
            <a-form-item>
              <a-button @click="getCellBaseInfoList" type="primary">查询</a-button>
            </a-form-item>
          </a-form>
        </div>
        <div class="map-control box-shadow">
          <a-checkbox-group
            v-model:value="baseControl"
            @change="clickMapControl">
            <span class="map-control-title">基础数据</span>
            <a-row>
              <a-col :span="12">
                <a-checkbox value="border">单元边界</a-checkbox>
              </a-col>
            </a-row>
            <span class="map-control-title">CFG数据</span>
            <a-row>
              <a-col :span="12">
                <a-checkbox value="design">设计点</a-checkbox>
              </a-col>
              <a-col :span="12">
                <a-checkbox value="fact">施工点</a-checkbox>
              </a-col>
            </a-row>
            <a-row>
              <a-col :span="12">
                <a-checkbox value="real_cfg">实时数据</a-checkbox>
              </a-col>
            </a-row>
          </a-checkbox-group>
        </div>
      </div>
      <div class="cell-table-box box-shadow">
        <div class="table-box-header">
          单元列表
        </div>
        <div class="table-box-center">
          <a-table
              :scroll="{y:setHeight('.table-box-center', 125) + 'px'}"
              :data-source="cellBaseInfoList.cellInfo"
              :rowKey="(record) => record.cellId"
              @change="getCellBaseInfoList"
              :pagination="{
                'current':cellBaseInfoList.startPage,
                'total':cellBaseInfoList.totalCount,
                'pageSize':cellBaseInfoList.everyPage,
                'showLessItems':true
              }">
            <a-table-column title="归属标段" data-index="sectionName"></a-table-column>
            <a-table-column title="单元名称" data-index="cellName"></a-table-column>
            <a-table-column title="工艺类型" data-index="kind" width="80px">
              <template #default="{text}">
                <div>{{kindDict.getNameByCode(text)}}</div>
              </template>
            </a-table-column>
            <a-table-column title="操作" data-index="cellId" width="50px">
              <template #default="{text,record}">
                <div class="table-icon-box">
                  <div @click="handleCell(record)">
                    <EditOutlined/>
                  </div>
                </div>
              </template>
            </a-table-column>
            <a-table-column title="启停" data-index="cellStatus" width="50px">
              <template #default="{text,record}">
                <a-switch :defaultChecked="text!=0" @change="setCellStatus(record)"/>
              </template>
            </a-table-column>
          </a-table>
        </div>
      </div>
    </div>
    <div class="right-box">
      <div class="base-info-box box-shadow">
        <a-descriptions :column="4">
          <a-descriptions-item label="单元名称" :span="1">
            {{inCellBaseInfo?inCellBaseInfo.cellName:'--'}}
          </a-descriptions-item>
          <a-descriptions-item label="创建时间" :span="1">
            {{inCellBaseInfo?inCellBaseInfo.gtmCreateTime:'--'}}
          </a-descriptions-item>
          <a-descriptions-item label="工艺类型" :span="1">
            {{inCellBaseInfo?kindDict.getNameByCode(inCellBaseInfo.kind):'--'}}
          </a-descriptions-item>
          <a-descriptions-item label="归属标段" :span="1">
            {{inCellBaseInfo?inCellBaseInfo.sectionName:'--'}}
          </a-descriptions-item>
          <a-descriptions-item label="区域面积" :span="1">
            {{inCellBaseInfo?inCellBaseInfo.area:'--'}}
          </a-descriptions-item>
          <a-descriptions-item label="创建账号" :span="1">
            {{inCellBaseInfo?inCellBaseInfo.userName:'--'}}
          </a-descriptions-item>
        </a-descriptions>
      </div>
      <div class="map-box box-shadow">
        <div class="map-event-control">
          <div @click="clickMapEvent" :class="{'map-control-button':true,'map-control-active':cfgPointInfo.active}">CFG信息</div>
        </div>
        <div
            class="point-info"
            v-show="cfgPointInfo.show">
          <div class="point-header">
            <span>
              CFG
            </span>
            <CloseOutlined @click="cfgPointInfo.show = false"/>
          </div>
          <div class="point-content">
            <div class="info">
              <a-row>
                <a-col :span="5">单元名称</a-col>
                <a-col :span="7">{{cfgPointInfo.cellName}}</a-col>
                <a-col :span="5">桩号</a-col>
                <a-col :span="7">{{cfgPointInfo.pointName}}</a-col>

                <a-col :span="5">设备编号</a-col>
                <a-col :span="7">{{cfgPointInfo.deviceSn}}</a-col>
                <a-col :span="5">设备名称</a-col>
                <a-col :span="7">{{cfgPointInfo.deviceName}}</a-col>

                <a-col :span="5">P坐标</a-col>
                <a-col :span="7">{{cfgPointInfo.a?cfgPointInfo.a.toFixed(2):""}}</a-col>
                <a-col :span="5">H坐标</a-col>
                <a-col :span="7">{{cfgPointInfo.b?cfgPointInfo.b.toFixed(2):""}}</a-col>

                <a-col :span="5">设计深度</a-col>
                <a-col :span="7">{{cfgPointInfo.depthDesign?cfgPointInfo.depthDesign:"0"}}m</a-col>
                <a-col :span="5">施工深度</a-col>
                <a-col :span="7">{{cfgPointInfo.depthBuild?cfgPointInfo.depthBuild:"0"}}m</a-col>

<!--                <a-col :span="5">设计倾斜度</a-col>-->
<!--                <a-col :span="7">{{cfgPointInfo.gradientDesign?cfgPointInfo.gradientDesign:"0"}}</a-col>-->
<!--                <a-col :span="5">施工倾斜度</a-col>-->
<!--                <a-col :span="7">{{cfgPointInfo.gradientBuild?cfgPointInfo.gradientBuild:"0"}}</a-col>-->

                <a-col :span="5">开始时间</a-col>
                <a-col :span="7">{{cfgPointInfo.startTime}}</a-col>
                <a-col :span="5">结束时间</a-col>
                <a-col :span="7">{{cfgPointInfo.endTime}}</a-col>
              </a-row>
            </div>
          </div>
        </div>
        <div @click="openExAreaModal(inCellBaseInfo?inCellBaseInfo.cellId:0)" class="ex-area-btn"/>
        <div @click="workListInfo.showModal = true" class="work-list-btn"/>
        <div class="tamp-legend">
          <div>
            <div class="legend">
              <div style="background: #0C7798"></div>
            </div>
            <div class="legend-title">设计点</div>
          </div>
          <div>
            <div class="legend">
              <div style="background: #0CDB34"></div>
            </div>
            <div class="legend-title">施工点</div>
          </div>
        </div>
        <div id="mapboxgl-box"></div>
      </div>
    </div>
  </div>
  <SModal
      title="工作设备列表"
      width="480"
      :is-show="workListInfo.showModal"
      @closed="()=>workListInfo.showModal=false">
    <div class="smodal-box smodal-to-cell">
      <a-table
          :scroll="{y:`205px`}"
          :data-source="workListInfo.workList"
          :rowKey="(record) => record.deviceId"
          @change="getToNextCellDevice"
          :pagination="false">
        <a-table-column title="机械编号" data-index="deviceSn"></a-table-column>
        <a-table-column title="机械名称" data-index="deviceName"></a-table-column>
        <a-table-column title="机械类型" data-index="deviceKind">
          <template #default="{text}">
            <div>{{deviceTypeDict.getNameByCode(text)}}</div>
          </template>
        </a-table-column>
      </a-table>
    </div>
  </SModal>
  <SModal
      title="排除区域"
      width="900"
      height="362"
      :is-show="showExModal"
      @closed="()=>{showExModal = false}">
    <div class="ex-area-modal">
      <div class="ex-table-box">
        <a-table
            :scroll="{y:'180px'}"
            :data-source="exAreaList"
            :pagination="false">
          <a-table-column title="排除时间" data-index="gtmCreateTime" width="120px"/>
          <a-table-column title="操作人员" data-index="userName" width="100px"/>
          <a-table-column title="排除区域名称" data-index="excludedName" width="160px">
            <template #default="{text,record}">
              <div style="padding: 0 8px">
                <a-input v-model:value="record.excludedName" v-if="record.excludedId<0"/>
                <span v-else>{{text}}</span>
              </div>
            </template>
          </a-table-column>
          <a-table-column title="排除原因" data-index="reason">
            <template #default="{text,record}">
              <div style="padding: 0 8px">
                <a-input v-model:value="record.reason" v-if="record.excludedId<0"/>
                <span v-else>{{text}}</span>
              </div>
            </template>
          </a-table-column>
          <a-table-column title="导入范围" width="100px" data-index="excludedId">
            <template #default="{text,record}">
              <a-button @click="openFileModal(record)" :disabled="excludedId>0" type="primary" ghost>导入</a-button>
            </template>
          </a-table-column>
          <a-table-column title="操作" width="60px" data-index="excludedId">
            <template #default="{text,record,index}">
              <div class="table-icon-box" style="padding: 0 5px; font-size: 16px">
                <div v-if="text<=0" @click="saveExArea(record)">
                  <SaveOutlined/>
                </div>
                <div v-if="text<=0" @click="delExArea(record,index)">
                  <DeleteOutlined/>
                </div>
                <div v-if="text>0" @click="delExArea(record,index)">
                  <DeleteOutlined/>
                </div>
              </div>
            </template>
          </a-table-column>
        </a-table>
      </div>
      <div class="ex-area-btn-box"><a-button @click="addExArea" type="primary">新增</a-button></div>
    </div>
    <input
        id="read-ex-area-input"
        @change="readBorderFile"
        accept=".txt"
        type="file"
        style="position:absolute;width:0;height:0;opacity:0"/>
  </SModal>
</template>

<script lang="ts">
import {useStore} from "vuex"
import {defineComponent,reactive,ref,toRefs,onMounted,onBeforeUnmount} from "vue"
import {setHeight} from "@/utils/tableUtils"
import {cellBaseInfo} from "@/hooks/cell/index"
import kindDict from "@/dicts/kindDict"
import cellStatusDict from "@/dicts/cellStatusDict"
import mapboxgl, {AnyLayer, LngLat, Marker, Sources} from "mapbox-gl"
import {EditOutlined,SaveOutlined,DeleteOutlined,CloseOutlined} from '@ant-design/icons-vue'
import {message} from "ant-design-vue"
import axios from "axios"
import qs from "qs"
import redLine from "@/assets/data/redLine.ts"
import "mapbox-gl/dist/mapbox-gl.css"
import {MqttOptions,MqttService} from "@/utils/mqttService"
import config from "@/config/index"
import SModal from "@/components/SModal/index.vue"
import deviceTypeDict from "@/dicts/deviceTypeDict"
import moment from 'moment'
import lodash from "lodash"

interface MapLayerRequestInfo{
  craft:string|null
  cellId:number|null
  type:string|null
}
class CFGPointInfo{
  cellId=-1
  cellName=""
  pointName=""
  deviceName=""
  deviceSn=""
  latitude=<any>undefined
  longitude=<any>undefined
  x=<any>undefined
  y=<any>undefined
  a=<any>undefined
  b=<any>undefined
  startTime=<any>undefined
  endTime=<any>undefined
  depthDesign=<any>undefined // 设计深度
  depthBuild=new Array<any>() // 施工深度
  gradientDesign=<any>undefined // 设计倾斜度
  gradientBuild=<any>undefined // 施工倾斜度
  active=false
  show=false
}
interface MapDeviceInfo{
  deviceId:number
  deviceInfo:any
  deviceMarker:Marker
}

export default defineComponent({
  setup(){
    const store = useStore()
    const userName = ref(JSON.parse(JSON.stringify(store.getters["userinfo/getUserInfo"])).username)
    const sections = ref(JSON.parse(JSON.stringify(store.getters["userinfo/getUserSection"])))
    const {
      cellQueryFormRef,cellQueryFormState,cellBaseInfoList,inCellBaseInfo,
      getCellBaseInfoList,setCellStatus,getCellBaseInfo
    } = cellBaseInfo()
    cellQueryFormState.value.sections[0].kind = [10]
    const workListInfo = ref({
      showModal: false,
      workList: new Array<any>()
    })
    const mapControl = reactive({
      baseControl: new Array<string>(),
      cfgPointInfo: new CFGPointInfo()
    })
    const exAreaInfo = reactive({
      uploadFileRecord: <any>null,
      showExModal: false,
      exAreaList: new Array<any>()
    })

    const realMapInfo = reactive({
      deviceList: new Array<MapDeviceInfo>(),  // 设备信息列表(主要用于marker)
      realSourceName: 'real_cfg',
      realSource: { // 实时施工数据源列表
        type: "FeatureCollection",
        features: new Array<any>(),
      },
      realLayerName: 'real_cfg', // 实时施工图层列表
      subscribeList: new Array<string>() // 订阅设备列表
    })

    let maps:any
    // 初始化地图
    const initMap = ()=>{
      mapboxgl.accessToken = config.map.accessToken
      let mapSource:Sources = {
        google: {
          type: "raster",
          tiles: [
            config.map.baseLayer1URL,
          ],
          tileSize: 256,
        },
      }
      let layers:AnyLayer[] = [
        {
          id: "google-tiles1",
          type: "raster",
          source: "google",
        },
      ]
      maps = {
        map:new mapboxgl.Map({
          container: "mapboxgl-box",
          style: {
            version: 8,
            sources: mapSource,
            layers: layers,
          },
          minZoom: 5,
          maxZoom:20,
          center: config.map.center,
          zoom: config.map.zoom,
          attributionControl: false
        }),
        sourceList: new Set<string>(),
        LayerList: new Set<string>()
      }

      maps.map.on("load",()=>{
        maps.map.addLayer({
          id: "satellite1",
          type: "raster",
          source: {
            type: "raster",
            tiles: [config.map.baseLayer2URL],
          },
        })
        maps.map.addLayer({
          id: "air",
          type: "raster",
          source: {
            type: "raster",
            tiles: [config.map.airUrl],
          },
        })
        maps.map.addSource("redLineSource",{type:"geojson",data:redLine})
        maps.map.addLayer({
          id: "redLineLayer",
          type: "line",
          source: "redLineSource",
          layout: {},
          paint: {
            "line-color":"#ff0000",
            "line-width":2,
            "line-opacity":1
          },
        })
      })

      maps.map.on("click", (e:any)=> {
        if (mapControl.cfgPointInfo.active) {
          getGetPointTimes(e.lngLat.lat, e.lngLat.lng).then((res: any) => {
                mapControl.cfgPointInfo = new CFGPointInfo()
                mapControl.cfgPointInfo.cellName = inCellBaseInfo.value.cellName
                if (res.data != null) {
                  Object.assign(mapControl.cfgPointInfo,res.data)
                  mapControl.cfgPointInfo.show = true
                } else {
                  mapControl.cfgPointInfo.show = false
                }
                mapControl.cfgPointInfo.active = true
              })
        }
      })
    }
    const getGetPointTimes = (latitude:number,longitude:number)=>{
      return new Promise((resolve,reject)=>{
        if(!inCellBaseInfo.value){
          message.info("请先选择单元后再进行操作")
          return
        }
        let cellId = inCellBaseInfo.value.cellId
        axios.post("/cfg/findPointTimes",
           {cellId,latitude,longitude}).then((res:any)=>{
          resolve(res)
        }).catch((err:any)=>{
          reject(err)
        })
      })
    }
    // 添加图层
    const addLayer = (layerInfo:MapLayerRequestInfo,callback:Function|null = null)=>{
      if(!maps.map) return
      maps.map.addLayer({
        id: `${layerInfo.type}`,
        type: "raster",
        source: `${layerInfo.type}`,
        paint: {
          "raster-opacity": 1, //图层显示透明度
        },
      })
      maps.LayerList.add(`${layerInfo.type}`)
    }
    // 添加数据源
    const addSource = (layerInfo:MapLayerRequestInfo,callback:Function|null = null)=>{
      if(!maps.map) return
      maps.map.addSource(`${layerInfo.type}`,{
        type: "raster",
        scheme:"tms",
        tiles: [
          `${config.map.geoServer}${layerInfo.craft}%3A${layerInfo.cellId}_${layerInfo.type}@EPSG%3A900913@png/{z}/{x}/{y}.png`
        ],
        tileSize: 256,
      })
      maps.sourceList.add(`${layerInfo.type}`)
    }
    // 移动地图视角
    const mapToCell = (cellCenter:LngLat)=>{
      if(!maps.map) return
      maps.map.jumpTo({center: cellCenter})
    }
    // 获取施工单元中正在工作设备列表
    const getCellWorkMachineryByCellId = (cell:any)=>{
      return new Promise((resolve, reject)=>{
        let data = {
          cellId: cell.cellId,
          kind: cell.kind
        }
        axios.post("common/findCellWorkMachineryByCellId",data).then((res:any)=>{
          resolve(res)
        }).catch((err:any)=>{
          reject(err)
        })
      })
    }
    // 列表中选择仓面
    const handleCell = (cell:any)=>{
      let f1 = getCellBaseInfo(cell)
      let f2 = getCellWorkMachineryByCellId(cell)
      Promise.all([f1,f2]).then((res:any)=>{
        // 1.持久化数据
        // 清除旧图层&数据源
        maps.LayerList.forEach((item:any)=>{
          if(maps.map.getLayer(item)){
            maps.map.removeLayer(item)
            maps.LayerList.delete(item)
          }
        })
        maps.sourceList.forEach((item:any)=>{
          if(maps.map.getSource(item)) maps.map.removeSource(item)
        })
        // 添加默认图层
        let layerInfo:MapLayerRequestInfo = {
          cellId:inCellBaseInfo.value.cellId,
          craft:"HaErBin-CFG",
          type:"border"
        }
        addSource(layerInfo)
        addLayer(layerInfo)

        // 2.实时数据
        // 先清除旧的实时显示相关的数据,图层,marker
        realMapInfo.deviceList.forEach((item:any)=>{
          item.deviceMarker.remove()
        })
        realMapInfo.deviceList = new Array<MapDeviceInfo>()
        MqttService.unsubscribe(realMapInfo.subscribeList)
        realMapInfo.subscribeList = new Array<string>()
        realMapInfo.realSource.features = new Array<any>()
        // 测试数据
        // realMapInfo.realSource.features.push({
        //   "type": "Feature",
        //   "geometry": {
        //     "type": "Point",
        //     "coordinates": [112.684343, 39.278525]
        //   }
        // })

        if(maps.map.getLayer(realMapInfo.realLayerName)) maps.map.removeLayer(realMapInfo.realLayerName)
        if(maps.map.getSource(realMapInfo.realSourceName)) maps.map.removeSource(realMapInfo.realSourceName)
        // 订阅新选定仓面的设备数据
        workListInfo.value.workList = res[1].data
        res[1].data.forEach((item:any)=>{
         // console.log("item.deviceSn"+item.deviceSn)
          let el = document.createElement("div")
          el.className = "device-cfg"
          el.innerText = `${item.deviceName}`

          realMapInfo.deviceList.push({
            deviceId:item.deviceId,
            deviceInfo:item,
            deviceMarker:new mapboxgl.Marker(el).setLngLat([0,0]).setOffset(new mapboxgl.Point(86,-16)).addTo(maps.map)
          })
          MqttService.subscribe(`${config.craft.cfg.mqtt.topic}${item.deviceSn}`)
        })

        // 3.操作界面
        mapControl.baseControl = ["border","real_cfg"]
        // 跳转位置
        if (res[0].data.centLat && res[0].data.centLon){
          maps.map.setZoom(17)
          let cellCenter = new mapboxgl.LngLat(res[0].data.centLon, res[0].data.centLat);
          mapToCell(cellCenter)
        }
      })
    }
    const clickMapControl = (res:any)=>{
      if(!inCellBaseInfo.value){
        message.info("请先选择单元后再进行操作")
        return
      }
      let diffList = res.concat(Array.from(maps.LayerList)).filter((cur:any, i:any, arr:any) => {
        return arr.indexOf(cur) === arr.lastIndexOf(cur);
      })
      diffList.forEach((item:any)=>{
        let layerInfo:MapLayerRequestInfo = {
          cellId:inCellBaseInfo.value.cellId,
          craft:"HaErBin-CFG",
          type:item
        }
        if(layerInfo.type!='real_cfg'){
          let layer = maps.map.getLayer(`${layerInfo.type}`)
          let source = maps.map.getSource(`${layerInfo.type}`)
          if(!layer && !source){
            // 增加图层及数据源
            addSource(layerInfo)
            addLayer(layerInfo)
          }else if(layer && source){
            // 移除图层
            maps.map.removeLayer(`${layerInfo.type}`)
            maps.LayerList.delete(`${layerInfo.type}`)
          }else if(!layer && source){
            // 增加图层
            addLayer(layerInfo)
          }
        }
      })
      let realTampIndex = diffList.indexOf("real_cfg")
      let realLayer = maps.map.getLayer("real_cfg")
      if(!maps.map.getSource(realMapInfo.realSourceName)) maps.map.addSource(realMapInfo.realSourceName,{type:'geojson',data:realMapInfo.realSource})
      if(realTampIndex>=0 && realLayer){ // 若存在,删除
        maps.map.removeLayer("real_cfg")
        maps.LayerList.delete(realMapInfo.realLayerName)
      }else if((realTampIndex>=0 && !realLayer) || realLayer){ // 若不存在,增加
        if(realLayer) maps.map.removeLayer("real_cfg")
        maps.map.addLayer({
          id: realMapInfo.realLayerName,
          type: "circle",
          source: realMapInfo.realSourceName,
          paint: {
            'circle-radius': {
              'base': 2,
              'stops': [[0,0],[20,4]]
            },
            'circle-color': "#0CDB34"
          }
        })
        maps.LayerList.add(realMapInfo.realLayerName)
      }
    }
    // {
    //   'base': 0,
    //     'stops': [[0,0],[10,10]]
    // }
    const clickMapEvent = ()=>{
      mapControl.cfgPointInfo.show = false
      mapControl.cfgPointInfo.active = !mapControl.cfgPointInfo.active
    }
    // 打开排除区域弹框
    const openExAreaModal = (cellId:number)=>{
      if(cellId<=0){
        message.info("请选择仓面后操作")
        return
      }
      axios.post("common/findCellExcludeAreaByCellId",{cellId:cellId}).then((res:any)=>{
        if(res.success){
          exAreaInfo.exAreaList = res.data
          exAreaInfo.showExModal = true
        }else{
          message.info("获取排除信息失败")
        }
      })
    }
    // 重新绘制边界
    const createTiledMap = (cellId:number)=>{
      return new Promise((resolve,reject)=>{
        axios.post("/cfgMap/reCreatBorder",
            qs.stringify({
              cellID:cellId,
              workType: 1
            }),{
              headers: {'Content-Type': 'application/x-www-form-urlencoded'}
            }).then((res:any)=>{
          resolve(res.success)
        })
      })
    }
    // 增加一列新的排除区域
    const addExArea = ()=>{
      exAreaInfo.exAreaList.push({
        cellId:inCellBaseInfo.value.cellId,
        excludedId: -1,
        excludedName: null,
        reason: null,
        userName: userName.value,
        border: {first:new Array(),second:new Array()},
        gtmCreateTime: moment().format('yyyy-MM-DD HH:mm:ss')
      })
    }
    // 保存排除区域
    const saveExArea = (record:any)=>{
      if (lodash.isEmpty(record.excludedName) || lodash.trim(record.excludedName).length==0) {
        message.info("请输入排除区域名称")
        return
      }
      if (record.border.first.length==0) {
        message.info("请录入排除区域边界")
        return
      }
      axios.post("/common/saveCellExcludeAreaByCellIdAB",{
        cellId:record.cellId,
        excludedId:record.excludedId,
        reason:record.reason,
        excludedName:record.excludedName,
        border:record.border
      }).then((res:any)=>{
        if(res.success){
          record.excludedId = res.data.excludedId
          createTiledMap(record.cellId)
          message.info("保存成功")
        }else{
          message.info(res.msg)
        }
      })
    }
    // 删除排除区域
    const delExArea = (record:any,index:number)=>{
      if(record.excludedId>0){
        axios.post("/common/deleteCellExcludeAreaByCellId",{
          cellId:inCellBaseInfo.value.cellId,
          excludedId:record.excludedId
        }).then((res:any)=>{
          if(res.success){
            exAreaInfo.exAreaList.splice(index,1)
            message.info("删除成功")
          }else{
            message.info(res.msg)
          }
        })
      }else{
        exAreaInfo.exAreaList.splice(index,1)
        message.info("删除成功")
      }
    }
    // 打开文件选择框
    const openFileModal = (record:any)=>{
      exAreaInfo.uploadFileRecord = record
      document.getElementById("read-ex-area-input")?.click()
    }
    // 读取边界数据
    const readBorderFile = ()=>{
      let inputDOM:any = document.getElementById("read-ex-area-input")
      let files = inputDOM.files

      if (files[0]) {
        let reader = new FileReader();
        reader.readAsText(files[0], "UTF-8");
        reader.onload = (e: any)=>{
          try{
            let fileStr = e.target.result
            let fileStrArr = fileStr.split(",,")
            exAreaInfo.uploadFileRecord.border.first = new Array()
            exAreaInfo.uploadFileRecord.border.second = new Array()

            for (let i = 0; i < fileStrArr.length; i++) {
              let pointArr = fileStrArr[i].split(",")
              if (pointArr.length == 2) {
                exAreaInfo.uploadFileRecord.border.first.push(parseFloat(pointArr[0]))
                exAreaInfo.uploadFileRecord.border.second.push(parseFloat(pointArr[1]))
              }
            }
          }catch (e){
            message.warn("导入格式错误"+e)
            console.log(e)
          }
        }
        inputDOM.value = "";
      }
    }

    onMounted(()=>{
      if(sections.value.length>0){
        cellQueryFormState.value.sections[0].sectionId = sections.value[0].sectionId
        getCellBaseInfoList(null)
      }
      // 加载地图
      initMap()
      // 初始化mqtt
      MqttService.init(
          `${config.craft.cfg.mqtt.ip}`,
          new MqttOptions(`${config.craft.cfg.mqtt.userName}`,`${config.craft.cfg.mqtt.password}`),
          (topic:any, msg:any) => {

            /**
             * 车辆图层
             * 先判断当前车辆在数据源中的位置
             * 若不存在车辆,则新增
             * 若存在,则修改当前记录
             */
            msg = JSON.parse(msg.toString())
            // console.log(`socket=1${JSON.stringify(msg)},${topic}`)
            let deviceListIndex = realMapInfo.deviceList.findIndex((item:any)=>{
              return item.deviceId == msg.deviceId
            })
            if(deviceListIndex<0) return

            realMapInfo.deviceList[deviceListIndex].deviceMarker.getElement().innerText = `${realMapInfo.deviceList[deviceListIndex].deviceInfo.deviceName},${msg.depth.toFixed(2)}m`
            realMapInfo.deviceList[deviceListIndex].deviceMarker.setLngLat([msg.longitude,msg.latitude])

            realMapInfo.realSource.features.push({
              "type": "Feature",
              "geometry": {
                "type": "Point",
                "coordinates": [msg.longitude,msg.latitude]
              }
            })

            if(maps.map.getLayer(realMapInfo.realLayerName)) maps.map.removeLayer(realMapInfo.realLayerName)
            if(maps.map.getSource(realMapInfo.realSourceName)) maps.map.removeSource(realMapInfo.realSourceName)

            maps.map.addSource(realMapInfo.realSourceName,{type:'geojson',data:realMapInfo.realSource})
            maps.map.addLayer({
              id: realMapInfo.realLayerName,
              type: "circle",
              source: realMapInfo.realSourceName,
              paint: {
                'circle-radius': {
                  'base': 2,
                  'stops': [[0,0],[20,4]]
                },
                'circle-color': "#0CDB34"
              }
            })
            maps.LayerList.add(realMapInfo.realLayerName)
          }
      )
    })

    onBeforeUnmount(()=>{
      // 关闭mqtt
      MqttService.unsubscribe(realMapInfo.subscribeList);
      MqttService.end();
      // 移除地图
      maps.map.remove()
    })

    return{
      sections,
      setHeight,
      kindDict,
      cellStatusDict,
      handleCell,
      ...toRefs(mapControl),
      clickMapControl,
      clickMapEvent,
      workListInfo,
      deviceTypeDict,

      cellQueryFormRef,
      cellQueryFormState,
      cellBaseInfoList,
      inCellBaseInfo,
      getCellBaseInfoList,
      setCellStatus,

      ...toRefs(exAreaInfo),
      openExAreaModal,
      addExArea,
      saveExArea,
      delExArea,
      openFileModal,
      readBorderFile,
    }
  },
  components:{EditOutlined,SaveOutlined,DeleteOutlined,CloseOutlined,SModal}
})
</script>

<style lang="scss" scoped>
.monitor-box{
  display: flex;
  width: 100%;
  height: 100%;
  .left-box{
    display: flex;
    flex-direction: column;
    width: 495px;
    height: 100%;
    .control-box{
      display: flex;
      width: 100%;
      height: 262px;
      .search-box{
        width: 235px;
        height: 100%;
        padding: 12px 17px;
        box-sizing: border-box;
        ::v-deep label{
          color:#666666;
        }
        ::v-deep .ant-form-item{
          display: flex;
          margin-bottom: 10px;
        }
        ::v-deep .ant-form-item-control-wrapper{
          flex: 1;
        }
        ::v-deep .ant-select{
          width: 100%;
        }
      }
      .map-control{
        width: 240px;
        height: 100%;
        margin-left: 20px;
        padding: 10px 17px;
        box-sizing: border-box;
        .map-control-title{
          color: #333333;
          font-weight: bold;
        }
        .map-control-title:nth-of-type(n + 2){
          display: inline-block;
          margin-top: 16px;
        }
        ::v-deep .ant-checkbox-group{
          .ant-checkbox-wrapper{
            width: 100px;
            margin-right: 0px;
            border: 2px solid #1890FF;
            box-sizing: border-box;
            border-radius: 2px;
            color: #1890FF;
            font-size: 12px;
            margin-top: 8px;
            padding: 2px 2px;
            box-sizing: border-box;
            >span:nth-of-type(n + 1){
              padding-left: 4px;
              padding-right: 4px;
            }
          }
          .ant-checkbox-wrapper:nth-child(odd){
            margin-right: 6px;
          }
          .ant-checkbox-inner{
            border: 1px solid #1890FF;
          }
        }
      }
    }
    .cell-table-box{
      display: flex;
      flex-direction: column;
      width: 495px;
      flex: 1;
      margin-top: 20px;
      padding: 0 13px;
      .table-box-header{
        color: #333333;
        font-size: 18px;
        font-weight: bold;
        padding: 18px 0 10px 10px;
      }
      .table-box-center{
        width: 100%;
        flex: 1;
      }
      ::v-deep .table-icon-box{
        display: flex;
        justify-content: space-around;
        >div:hover{
          color: #1677FF;
        }
      }
    }
  }
  .right-box{
    display: flex;
    flex-direction: column;
    flex: 1;
    height: 100%;
    margin-left: 20px;
    .base-info-box{
      width: 100%;
      height: 82px;
      padding: 14px 0 0px;
    }
    .map-box{
      position: relative;
      flex: 1;
      width: 100%;
      height: 100%;
      margin-top: 20px;
      box-sizing: border-box;
      .point-info{
        z-index: 1;
        .point-header{
          display: flex;
          width: 100%;
          height: 34px;
          line-height: 34px;
          padding: 0 16px;
          box-sizing: border-box;
          justify-content: space-between;
          border-bottom: 1px solid #eeeeee;
          >span{
            font-weight: bold;
          }
          ::v-deep .anticon{
            line-height: 34px;
          }
        }
      }
      .point-info{
        display: flex;
        flex-direction: column;
        position: absolute;
        top: 40px;
        right: 5px;
        width: 520px;
        height: 230px;
        background: #FFFFFF;
        box-shadow: 0px 2px 16px 0px rgba(0, 0, 0, 0.08);
        border-radius: 2px;
        box-sizing: border-box;
        .point-content{
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
          width: 100%;
          padding: 0 16px;
          .info{
            width: 100%;
            ::v-deep .ant-row{
              width: 100%;
              line-height: 37px;
              .ant-col:nth-child(odd){
                color: #666666;
                font-weight: bold;
              }
              .ant-col:nth-child(even){
                color: #666666;
              }
            }
          }
        }
      }
      .map-event-control{
        display:flex;
        position:absolute;
        top:5px;
        right:5px;
        height:30px;
        background-color: #FFFFFF;
        border-radius: 3px;
        z-index: 10;
        overflow: hidden;
        .map-control-button{
          width: 90px;
          height: 30px;
          font-size: 14px;
          line-height: 28px;
          text-align: center;
          border: 1px solid #f0f0f0;
          box-sizing: border-box;
          cursor:pointer;
        }
        .map-control-active{
          color: #1890FF;
        }
        .map-control-disable{
          color: #8d8d8d;
        }
      }
      #mapboxgl-box{
        display: flex;
        width: 100%;
        height: calc(100% - 6px);
        box-sizing: border-box;
      }
      .tamp-legend{
        position: absolute;
        display: flex;
        flex-direction: column;
        padding: 8px 2.5px;
        width: 84px;
        height: 72px;
        right: 5px;
        bottom: 12px;
        background: #FFFFFF;
        border-radius: 3px;
        box-sizing: border-box;
        z-index: 1;
        >div{
          display: flex;
          width: 100%;
          height: 28px;
          .legend{
            display: flex;
            justify-content: center;
            align-items: center;
            width: 28px;
            height: 28px;
            >div{
              width: 12px;
              height: 12px;
              border-radius: 50%;
            }
          }
          .legend-title{
            color: #666666;
            line-height: 28px;
            text-align: center;
          }
        }
      }
      .ex-area-btn{
        position: absolute;
        left: 5px;
        bottom: 12px;
        width: 32px;
        height: 32px;
        background: url("../../../assets/image/ex_area.png") center no-repeat;
        background-size: 18px;
        background-color: #E6F1FC;
        border: 1px solid #1677FF;
        box-sizing: border-box;
        z-index: 1;
      }
      .work-list-btn{
        position: absolute;
        left: 42px;
        bottom: 12px;
        width: 32px;
        height: 32px;
        background: url("../../../assets/image/work_list.png") center no-repeat;
        background-size: 18px;
        background-color: #E6F1FC;
        border: 1px solid #1677FF;
        box-sizing: border-box;
        z-index: 1;
      }
    }
  }
}
.smodal-box{
  box-sizing: border-box;
}
.smodal-to-cell{
  width: 100%;
  height: 100%;
}
.ex-area-modal{
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  .ex-table-box{
    flex: 1;
    padding-top: 10px;
  }
  .ex-area-btn-box{
    display: flex;
    justify-content: flex-end;
    width: 100%;
    height: 48px;
  }
}
</style>

